package com.brotherly.geo;

public class MapIntegerPoint
{
    static final char[] table =
    {
            'a', 'b', 'e', 'f', 'n', 'm', 'k', 'l', 'g', 'h'
    };

    public MapIntegerPoint(long lon, long lat)
    {
        longitude = lon;
        latitude = lat;
    }

    public long longitude;
    public long latitude;

    public String getGarbleString()
    {
        StringBuilder builder = new StringBuilder();

        builder.append(garble(longitude));
        builder.append(',');
        builder.append(garble(latitude));

        return builder.toString();
    }

    public double getDistance(MapIntegerPoint point)
    {
        return distance(this.longitude, this.latitude, point.longitude, point.latitude);
    }

    public MapDoublePoint toMapDoublePoint()
    {
        return new MapDoublePoint(longitude / 1e5, latitude / 1e5);
    }

    public static MapIntegerPoint getUngarblePoint(String text)
    {
        int index = text.indexOf(',');
        if (index == -1)
            return null;

        String strLon = text.substring(0, index);
        String strLat = text.substring(index + 1);

        return new MapIntegerPoint(ungarble(strLon), ungarble(strLat));
    }

    public static String garble(long value)
    {
        StringBuilder builder = new StringBuilder();

        if (value == 0)
        {
            builder.append(table[(int) value]);
        } else
        {
            while (value != 0)
            {
                int index = (int) (value % 10);

                builder.insert(0, table[index]);

                value /= 10;
            }
        }

        return builder.toString();
    }

    public static long ungarble(String text)
    {
        long value = 0;

        for (int index = 0; index != text.length(); ++index)
        {
            char ch = text.charAt(index);

            for (int num = 0; num != table.length; ++num)
            {
                if (ch == table[num])
                {
                    value = value * 10 + num;
                    break;
                }
            }
        }

        return value;
    }

    public static double distance(long longitude1, long latitude1, long longitude2, long latitude2)
    {
        double pt1[] = new double[2];
        double pt2[] = new double[2];

        double value = 0;

        pt1[0] = Math.toRadians(longitude1 / 1e5);
        pt1[1] = Math.toRadians(latitude1 / 1e5);

        pt2[0] = Math.toRadians(longitude2 / 1e5);
        pt2[1] = Math.toRadians(latitude2 / 1e5);

        value = MapDoublePoint.computeDistanceAndBearing(pt1[1], pt1[0], pt2[1], pt2[0], null);

        return value;
    }
}
